Skip to main content

JavaScript Aspect — Security Questionnaire (Vendor Response)

This page is the canonical, pre-filled vendor response to the JavaScript Aspect Architecture, Security, and Compatibility Questionnaire that FI security / AppSec teams use during partner due-diligence reviews.

Rather than asking every FI to independently re-derive how a Forge-CLI-emitted Aspect answers each question, this page ships:

  1. The 60 questions verbatim (anchored, so other docs can deep-link).
  2. A coverage matrix showing which Forge templates address which question groups.
  3. Per-template completed responses for the three templates that cross trust boundaries — oidc-snippet, hidden-iframe-sso, mobile-vendor-chat-jsbridge.
  4. A shared response summary for the remaining 12 templates grouped by family.

How to use this page:

  • FI AppSec reviewer — open the per-template response for the template being submitted, verify each pre-filled answer matches the deployment, sign off using the Deployment Security Checklist.
  • Partner integrator — when authoring custom snippets that don't go through forge aspect submit, treat the per-template responses as a target spec.
  • Candescent contributor — when adding a new template or security control, update both the Security Architecture page and this page so question coverage stays accurate.

Each answer is tagged:

  • ✓ CLI — the Forge CLI enforces this property in every emitted snippet. FI verification is mechanical (e.g. grep for an inlined helper).
  • ◯ FI — the property exists but requires FI configuration, deployment validation, or downstream wiring. Listed so AppSec teams know what they own.
  • n/a — the question does not apply to this template (e.g. SRI on a template that loads no external scripts).

The Questionnaire

Source: JavaScript Aspect Architecture, Security, and Compatibility Questionnaire — Candescent partner due-diligence intake. Classified as Highly Confidential. Quoted verbatim below for traceability.

Section 1 — End-to-End Architecture Overview

Q1. Architecture diagram

Provide a high-level architecture diagram showing: parent FI Digital Banking application; embedded static loader script; runtime services and APIs; UI rendering mechanism (DOM, Shadow DOM, iframe); logging / analytics endpoints.

Q2. Parties involved

List all parties involved (e.g., Elan, TransUnion, subcontractors).

Q3. Per-party responsibilities

For each party, describe: responsibilities; systems owned; data processed; operational support ownership.

Q4. Layer ownership

Identify which party hosts the static loader script, runtime APIs, owns offer logic, owns UI rendering, owns logging and analytics.

Section 2 — Script Execution Model & Trust Boundaries

Q5. Parent-window execution

What JavaScript executes directly in the parent window context?

Q6. Execution placement

What functionality executes in the parent DOM / inside Shadow DOM / inside a sandboxed iframe?

Q7. Trust boundaries

Describe the trust boundaries between: parent FI site; static loader; runtime services; partner systems.

Q8. Approved runtime domains

How are approved runtime domains defined, enforced, and validated?

Section 3 — Static vs. Dynamic Content (SRI Model)

Q9. Static loader responsibilities

Describe the responsibilities of the static loader script: initialization; context setup; event registration; runtime fetch orchestration.

Q10. Dynamic runtime content

Describe what logic exists in dynamic runtime content: offer eligibility; campaign logic; UI configuration; personalization rules.

Q11. Immutability + SRI

Confirm: static loader is immutable and versioned; static loader supports Subresource Integrity (SRI); dynamic content does not introduce new executable entry points.

Section 4 — Context, State & Authentication Handling

Q12. Contextual data passed

What contextual data is passed from the parent site to the JS Aspect? (Customer identifiers, session identifiers, authentication state, page context.)

Q13. Context-passing mechanism

How is context passed? (Script attributes, global variables, postMessage, URL parameters.)

Q14. Context validation & sanitization

How is context validated, sanitized, and protected from spoofing or replay?

Q15. Auth context shared with parent

How is authenticated context shared with the parent window? (postMessage, cookies, tokens, other.)

Q16. Forgery / misuse protection

What guarantees ensure authenticated context cannot be forged or misused?

Section 5 — Communication Back to the Parent Website

Q17. Communication mechanism

How does the JS Aspect communicate actions or results back to the parent site? (postMessage, DOM events, callbacks.)

Q18. Message format / schema

What message formats and schemas are used?

Q19. Message origin / source validation

How is message origin and source validated? (event.origin, event.source, schema validation.)

Q20. Triggerable parent-site actions

What parent-site actions can be triggered as a result?

Section 6 — Rendering & XSS Protections

Q21. Render location of dynamic data

Where is dynamic remote data rendered?

Q22. innerHTML usage

Is innerHTML used? If yes, list all usage locations.

Q23. XSS prevention measures

Explain security measures in place to prevent XSS, including: output encoding, sanitization libraries, HTML allow-listing, escaping strategies.

Q24. Dangerous primitives

Confirm whether the solution uses: eval, new Function, inline script injection.

Section 7 — UI & Design System Integration

Q25. Vendor styling level

Is the UI dialog fully vendor-styled, partially customizable, or fully themeable?

Q26. Customizable UI elements

What UI elements can be customized to match the parent site's design system? (Colors, fonts, layout, button labels.)

Q27. CSS isolation

How is CSS isolation handled? (Shadow DOM, iframe, scoped CSS conventions.)

Q28. Parent-CSS impact

Can parent-site CSS break or visually impact the UI?

Section 8 — Error Handling, Timeouts & Resiliency

Q29. Failure modes

What happens if the static loader fails to load? Runtime APIs time out? A partner API is unavailable?

Q30. Timeout thresholds

What timeout thresholds are used?

Q31. UX during failures

What user experience is presented during partial failures, full failures, slow responses?

Q32. Fail-open vs fail-closed

Is the behavior fail-open or fail-closed?

Q33. Retry handling

How are retries handled?

Section 9 — Troubleshooting & Operational Support

Q34. Troubleshooting workflow

How is troubleshooting performed when an FI reports an issue?

Q35. Telemetry & diagnostics

What telemetry or diagnostics are available? (Client-side logs, correlation IDs, error codes.)

Q36. First responder

Which party is the first responder for UI issues, API failures, authentication issues?

Q37. Coordination cost

How many parties must coordinate to resolve a typical incident?

Section 10 — Logging, Analytics & User Activity

Q38. Activities logged externally

What user activities are logged externally, in addition to CTA clicks? (Page load, dialog open/close, scroll, hover, form input, errors.)

Q39. Log data elements

What data elements are included in logs?

Q40. Identity binding in logs

Are logs tied to customer identity, session identity, anonymous identifiers?

Q41. Log retention

Where are logs stored and for how long?

Section 11 — JavaScript Libraries & Dependency Management

Q42. Third-party libraries

List all third-party JavaScript libraries used.

Q43. Library delivery

Are libraries bundled, loaded dynamically, referenced from CDNs?

Q44. Library conflict prevention

How are library conflicts prevented when running inside the parent window? (Namespacing, bundling, Shadow DOM, iframe isolation.)

Q45. Global variables

Are any globally scoped variables introduced? If yes, list them.

Section 12 — Script Compatibility with FI Environment

Q46. FI script compatibility

Describe how the JS Aspect ensures compatibility with existing FI scripts, including analytics, fraud tools, accessibility tooling, and tag managers.

Q47. Parent-site global dependencies

Does the script depend on or interact with any parent-site globals? If yes, list dependencies.

Q48. FI framework conflicts

How does the script avoid conflicts with common FI frameworks? (React / Angular / Vue, jQuery, AMD / RequireJS, tag managers.)

Q49. Global event listeners

Does the script register global event listeners? (window, document, message, keydown, click, etc.)

Q50. Event scoping / namespacing

How are events scoped or namespaced to avoid interference?

Q51. Failure containment

How is failure contained so errors do not break other FI scripts or page rendering?

Q52. Performance impact

What impact does the script have on page load, main thread usage, rendering performance?

Q53. Async / non-blocking execution

Is execution asynchronous? Non-blocking?

Q54. Behavior in script-heavy environments

How does the script behave in script-heavy FI environments?

Section 13 — Change Management & Governance

Q55. Change classification

What changes require a static loader update vs runtime config update only?

Q56. Breaking-change communication

How are breaking changes communicated?

Q57. Backward compatibility

How is backward compatibility maintained?

Q58. Rollback strategy

What is the rollback strategy if an update causes issues?

Section 14 — Compliance & Assurance

Q59. Security review

Has the solution been reviewed by internal AppSec? External assessors?

Q60. Pen-test / code-review artifacts

Are penetration test or code review artifacts available?


Coverage Matrix

Summary view: rows = questionnaire sections, columns = template families. Cells indicate whether the Forge CLI enforces the controls in that section by default (✓), requires FI configuration / verification (◯), or the section does not apply (—).

SectionUI templates¹Personalized UI²Vendor loaders³oidc-snippethidden-iframe-ssomobile-vendor-chat-jsbridge
1 — Architecture (Q1-4)
2 — Trust boundaries (Q5-8)
3 — Static vs dynamic / SRI (Q9-11)◯ FI sets --integrity◯ FI sets --integrity
4 — Context handling (Q12-16)
5 — Communication back to parent (Q17-20)◯ FI wires backend
6 — Rendering / XSS (Q21-24)
7 — UI / design system (Q25-28)n/an/a
8 — Resiliency (Q29-33)
9 — Troubleshooting (Q34-37)partialpartialpartial✓ correlation id✓ correlation id✓ correlation id
10 — Logging (Q38-41)◯ FI pipeline◯ FI pipeline◯ FI pipeline◯ FI pipeline◯ FI pipeline◯ FI pipeline
11 — Libraries (Q42-45)◯ vendor SDK◯ vendor SDK
12 — FI compatibility (Q46-54)
13 — Change management (Q55-58)✓ submit-time✓ submit-time✓ submit-time✓ submit-time✓ submit-time✓ submit-time
14 — Compliance (Q59-60)◯ FI review◯ FI review◯ FI review◯ FI review◯ FI review◯ FI review

¹ banner, toast, card, modal, countdown, floating-action-button ² welcome-banner, personalized-toast ³ vendor-script-loader, vendor-script-with-config, tag-manager, vendor-sdk-personalized


Per-Template Responses — High-Leverage Templates

The three templates that cross trust boundaries get full per-question responses. All other templates share grouped summaries below.

oidc-snippet — Completed Response

Full OIDC authorization-code-flow scaffold. Targets local Toolkit (auto-config) or FI Keycloak (--client-id / --fi-domain).

Section 1 — Architecture (Q1-4)

#StatusEvidence / How
Q1✓ CLIArchitecture diagram in Security Architecture. Parent window → static loader IIFE → __cdxFetch to OIDC endpoint → console.* logs (no analytics endpoint).
Q2✓ CLIThree parties: FI (host shell, dbk API, OIDC backend exchange); Candescent (Forge CLI, generated snippet); OIDC IdP (Keycloak / Toolkit, returns authorization code).
Q3✓ CLISee party-responsibility table in Security Architecture.
Q4✓ CLIStatic loader hosted by FI; runtime API (/auth/realms/.../auth) hosted by FI or federated IdP; offer logic / UI rendering owned by FI; logging owned by FI (browser-log pipeline).

Section 2 — Trust Boundaries (Q5-8)

#StatusEvidence / How
Q5✓ CLIThe full IIFE runs in the parent window. No iframe, no Shadow DOM.
Q6✓ CLIParent DOM only. oidc-snippet does not use iframe or Shadow DOM.
Q7✓ CLIFI ↔ OIDC IdP boundary crossed via HTTPS fetch; auth code returned to parent JS, then FI's responsibility to forward to backend. See Trust Zones.
Q8◯ FIOIDC endpoint domain set via --fi-domain at submission time. FI verifies the submitted snippet's hardcoded domain matches the approved IdP.

Section 3 — Static vs Dynamic / SRI (Q9-11)

#StatusEvidence / How
Q9✓ CLIStatic loader handles: auth-URL construction, fetch-with-retry, response parsing, toast UX. No personalization or campaign logic.
Q10✓ CLIDynamic content = OIDC authorization code (opaque string) returned by IdP. Code does not introduce new executable entry points; it is forwarded to the FI backend by FI-controlled glue code.
Q11✓ CLIEach forge aspect submit produces an immutable IIFE. SRI on script tags is n/a (no external script loaded by oidc-snippet); the loader itself is FI-hosted and would be SRI-protected by the FI's own page.

Section 4 — Context Handling (Q12-16)

#StatusEvidence / How
Q12✓ CLIclientId (configured at submit time), redirectUri (computed from window.location.origin).
Q13✓ CLIURL query parameters on the /authorize request. credentials: 'include' forwards FI session cookies.
Q14✓ CLIclientId is hardcoded into the snippet at generation time; redirectUri is derived from window.location.origin (browser-trusted). Authorization code returned by IdP is treated as opaque — FI backend validates it.
Q15◯ FIThe authorization code surfaces in console.log and as the toast detail. FI is responsible for wiring the code from the front-end to the backend (typically via fetch to an FI API).
Q16◯ FIOIDC's standard PKCE / state / nonce parameters are the FI backend's responsibility. The CLI's emitted snippet does not inject or validate these — current scaffolding is auth-code only; FIs that need PKCE must extend the snippet.

Section 5 — Communication Back to Parent (Q17-20)

#StatusEvidence / How
Q17◯ FIoidc-snippet does not communicate back. It logs the authorization code; FI custom code reads the log or extends the snippet.
Q18n/aNo postMessage in this template.
Q19n/aNo postMessage listener.
Q20n/aNone directly; FI backend's response drives any parent-site action.

Section 6 — Rendering & XSS (Q21-24)

#StatusEvidence / How
Q21✓ CLIA toast inside the parent DOM. Toast contents: clientId, truncated authorization code, redirect URL — all string-coerced and __cdxEsc-escaped.
Q22✓ CLIYes — toast HTML is built via el.innerHTML = '...' with string concatenation. All interpolated values pass through __cdxEsc.
Q23✓ CLIOutput encoding via __cdxEsc (escapes & < > " ' /). No third-party sanitizer needed.
Q24✓ CLINo eval, no new Function, no inline <script> injection, no inline onclick= (all event handlers via addEventListener).

Section 7 — UI / Design System (Q25-28)

#StatusEvidence / How
Q25Toast is fully Forge-styled (no FI theming hooks at this time).
Q26Limited customization — no --bg-color / --text-color flags on oidc-snippet.
Q27◯ FINo Shadow DOM. Tracked work; until shipped, FI must verify parent-CSS impact. CSP nonce on inline <style> is ✓ via --csp-nonce.
Q28◯ FIParent CSS can affect the toast. FI must validate at deploy time.

Section 8 — Resiliency (Q29-33)

#StatusEvidence / How
Q29✓ CLIOIDC endpoint timeout / 5xx / network error → user-facing toast with timeout-specific hint, all logged with correlation id.
Q30✓ CLIDefault 10 000 ms via inlined __cdxFetch. Override --timeout-ms <1000-60000>.
Q31✓ CLIRed-background error toast distinguishes timeout (Request timed out after Xms) from other failures (HTTP 4xx/5xx). Hint: "increase --timeout-ms or check the network."
Q32✓ CLIFail-closed on auth (no code → no downstream action). Fail-open on telemetry (correlation id missing → still emits log without prefix).
Q33✓ CLIDefault 3 retries on 5xx / network errors with exponential backoff (1s → 2s → 4s, capped at 8s). 4xx never retried. Override --max-retries <0-5> / --retry-delay-ms.

Section 9 — Troubleshooting & Operational Support (Q34-37)

#StatusEvidence / How
Q34✓ CLIFI on-call greps browser logs for [cdx-aspect:<correlation-id>] to isolate a specific deployment. See Correlation IDs.
Q35✓ CLIAuto-generated correlation id on every console.* line. Override via --correlation-id "$RELEASE_ID" to chain logs from CI / release pipeline.
Q36◯ FIUI issues / browser-log review → FI. OIDC endpoint failures → FI (IdP owner). Token-exchange failures → FI (backend).
Q37◯ FITypically 1-2 parties (FI + IdP). The CLI itself does not enter incident response post-deployment.

Section 10 — Logging (Q38-41)

#StatusEvidence / How
Q38◯ FIForge CLI logs only to console.*. No external sink is shipped — FI's existing browser-log pipeline (Sentry, Datadog Browser, etc.) consumes the logs.
Q39✓ CLIPer log line: correlation id; the message; truncated code (≤ 20 chars); truncated redirect URL (≤ 50 chars). No PII, no full token.
Q40◯ FILogs are not tied to customer identity by default. FI's browser-log pipeline can correlate via session cookie if their logger captures it.
Q41◯ FIRetention is FI's browser-log policy.

Section 11 — Libraries & Dependencies (Q42-45)

#StatusEvidence / How
Q42✓ CLINone. The emitted IIFE is plain ES6+ standalone code.
Q43✓ CLIBundled — single static IIFE, no dynamic imports, no CDN references.
Q44✓ CLIIIFE scope plus __cdx* prefix on every internal helper (__cdxFetch, __cdxEsc, etc.).
Q45✓ CLINone introduced. (No window.* writes.)

Section 12 — FI Compatibility (Q46-54)

#StatusEvidence / How
Q46✓ CLIIIFE-scoped; no global pollution; no inline onclick= (compatible with strict CSP); CSP-nonce-aware via --csp-nonce. Co-exists with analytics, fraud, a11y, tag-manager scripts.
Q47✓ CLINone. oidc-snippet does not read dbk.*.
Q48✓ CLINo framework dependency. Works under React / Angular / Vue / jQuery / AMD without modification.
Q49✓ CLIOnly el.addEventListener('animationend', ...) and closeBtn.addEventListener('click', ...) — both attached to elements the snippet itself created. No window / document / message listeners.
Q50✓ CLIListeners attached to specific elements (toast, dismiss button) — not delegated.
Q51✓ CLIAll async paths wrapped in .catch(...) that logs and shows the error toast. No throw escapes the IIFE.
Q52✓ CLIMinimal page-load impact. Single fetch, no DOM observers, no event-loop work post-render.
Q53✓ CLI__cdxFetch is Promise-based; setTimeout for the timeout abort.
Q54✓ CLISelf-contained. No global mutation, no DOM mutation outside the toast element.

Section 13 — Change Management (Q55-58)

#StatusEvidence / How
Q55✓ CLIAll changes are static-loader updates. There is no separate runtime config. Each forge aspect submit produces a new IIFE.
Q56◯ FIFI's responsibility to communicate Aspect changes through their internal release process.
Q57✓ CLI submit-timeThe dbk-API contract is the long-running compatibility surface; templates always type-check dbk.* before use, so missing methods degrade gracefully.
Q58◯ FIStandard Git revert on the FI extension repo's submission PR + redeploy.

Section 14 — Compliance & Assurance (Q59-60)

#StatusEvidence / How
Q59◯ FIThe Forge CLI's internal AppSec review is documented in cdx-forge-cli/SECURITY_IMPLEMENTATION_PLAN.md. Each FI deployment requires the FI's own AppSec review of the submitted PR — see Deployment Security Checklist.
Q60◯ FIFI's responsibility post-deployment.

hidden-iframe-sso — Completed Response

Mounts a 0×0 sandboxed iframe pointed at a vendor SSO handoff URL; receives a token via postMessage; dispatches a validated custom event for FI consumers.

Section 1 — Architecture (Q1-4)

#StatusEvidence / How
Q1✓ CLIParent window IIFE → mounts hidden iframe → receives postMessage from sandboxed iframe → dispatches cdx-aspect:sso-token CustomEvent. See Trust Zones.
Q2✓ CLIFI, Candescent (CLI), SSO endpoint provider (FI's IdP or federated partner).
Q3✓ CLISame as oidc-snippet. SSO endpoint provider owns the iframe handoff page + postMessage payload schema.
Q4✓ CLIStatic loader = FI-hosted; SSO endpoint = FI or federated IdP; UI rendering = none (iframe is invisible).

Section 2 — Trust Boundaries (Q5-8)

#StatusEvidence / How
Q5✓ CLIOuter IIFE runs in parent. Inner SSO logic runs in sandboxed iframe (separate execution context).
Q6✓ CLIMixed: parent DOM (mount logic + message listener) + sandboxed iframe (SSO endpoint code). No Shadow DOM.
Q7✓ CLIIframe is the trust boundary; postMessage is the only data path. Sandbox attribute caps iframe permissions. See SSO iframe hardening.
Q8✓ CLIIframe origin always trusted. Extra origins via --allowed-origins 'https://idp.partner.com,*.federation.example.com' (validated at generation; bad origins dropped silently). Inlined __cdxValidateMessageOrigin enforces at runtime.

Section 3 — Static vs Dynamic / SRI (Q9-11)

#StatusEvidence / How
Q9✓ CLIStatic loader: iframe mount, sandbox attribute, message listener wiring, schema validation, custom-event dispatch.
Q10✓ CLIDynamic content = SSO token payload. Schema-validated by __cdxValidateSsoMessage. Unknown fields stripped before dispatch.
Q11✓ CLIStatic loader is immutable per submission. SRI on the iframe content is the SSO endpoint's CSP responsibility, not the parent.

Section 4 — Context Handling (Q12-16)

#StatusEvidence / How
Q12✓ CLIOptional dbk.isWebview() gate for mobile-only execution. No personally identifying data passed to iframe; iframe authenticates via parent-window cookies (same-origin sandbox token).
Q13✓ CLIIframe src URL only. Cookies via allow-same-origin sandbox token.
Q14✓ CLIiframeSrc validated as parseable URL at generation time. dbk.isWebview() return value type-checked at runtime. SSO payload validated by __cdxValidateSsoMessage.
Q15✓ CLIcdx-aspect:sso-token CustomEvent dispatched on window with bubbles:false, composed:false. Detail: {type, token, expiry?, signature?} only — unknown fields stripped.
Q16✓ CLI + ◯ FIOrigin allowlist prevents foreign windows from posting forged tokens. Token expiry validated (Date.now() < expiry). Signature is type-checked only — FI must perform HMAC verification in their cdx-aspect:sso-token consumer.

Section 5 — Communication Back to Parent (Q17-20)

#StatusEvidence / How
Q17✓ CLIDOM event: window.dispatchEvent(new CustomEvent('cdx-aspect:sso-token', {detail, bubbles:false, composed:false})).
Q18✓ CLIStrict schema: type === 'sso-token'; token non-empty string ≤ 4096 chars; expiry optional future Unix-ms; signature optional string ≤ 1024 chars.
Q19✓ CLIevent.origin matched against inlined __cdxAllowedOrigins array (iframe origin + caller-supplied entries). Untrusted origins logged and dropped.
Q20✓ CLIOnly the dispatched cdx-aspect:sso-token event. FI consumer code decides what to do with the token.

Section 6 — Rendering & XSS (Q21-24)

#StatusEvidence / How
Q21✓ CLIHidden iframe (0×0, aria-hidden="true"). No visible UI.
Q22✓ CLINo innerHTML of dynamic data. The iframe's own content is opaque to the parent IIFE.
Q23✓ CLIIframe sandbox + origin allowlist + message-schema validation jointly prevent XSS through the SSO channel.
Q24✓ CLINo eval / new Function / inline scripts / inline event handlers.

Section 7 — UI / Design System (Q25-28)

#StatusEvidence / How
Q25n/aNo visible UI.
Q26n/aNo visible UI.
Q27n/aIframe is invisible; CSS isolation only matters for the SSO endpoint's internal styling (its CSP responsibility).
Q28n/aNo visible UI.

Section 8 — Resiliency (Q29-33)

#StatusEvidence / How
Q29✓ CLIiframe load failure: silent (FI consumer never receives token, falls back to its own timeout). Untrusted origin: dropped + logged. Schema-validation failure: dropped + logged.
Q30◯ FINo timeout on the iframe load itself. FI's responsibility to set a wall-clock fallback in the consumer of cdx-aspect:sso-token.
Q31◯ FINo UX (template renders no UI). FI's downstream consumer drives any UI.
Q32✓ CLIFail-closed. Untrusted origins, malformed payloads, expired tokens — all silently dropped. The custom event never fires for invalid input.
Q33◯ FINo retry. Single iframe load; if it fails, the FI consumer's fallback handles it.

Section 9 — Troubleshooting (Q34-37)

#StatusEvidence / How
Q34✓ CLIAll hidden-iframe-sso log lines tagged with [cdx-aspect:<correlation-id>]. Common signals: blocked message from untrusted origin, sso-token payload failed schema validation, host element not found.
Q35✓ CLIAuto-generated correlation id; override via --correlation-id.
Q36◯ FIiframe content / postMessage payload changes → SSO endpoint owner. Mount-time issues (host selector not found) → FI front-end team.
Q37◯ FITypically 2 parties (FI + SSO endpoint provider).

Section 10 — Logging (Q38-41)

Same as oidc-snippet: correlation-tagged console.* only; FI's browser-log pipeline consumes; no PII; FI controls retention.

Section 11 — Libraries (Q42-45)

#StatusEvidence / How
Q42✓ CLINone.
Q43✓ CLIBundled IIFE.
Q44✓ CLIIIFE scope, __cdx* prefixed helpers (__cdxValidateMessageOrigin, __cdxValidateSsoMessage, __cdxAllowedOrigins).
Q45✓ CLINone introduced. (Iframe element id cdx-sso-iframe is on document, not window.)

Section 12 — FI Compatibility (Q46-54)

#StatusEvidence / How
Q46✓ CLISame as oidc-snippet.
Q47✓ CLIReads dbk.isWebview (optional, type-checked) when webviewGate: true.
Q48✓ CLINo framework dependency.
Q49✓ CLI + ◯ documentedOne window.addEventListener('message', ...) listener — origin-validated against the inlined allowlist, payload schema-validated. This is the only template that registers a global listener.
Q50✓ CLIThe message listener filters by origin before processing; foreign messages return early.
Q51✓ CLIListener body wraps only schema-validated dispatch; no throw paths.
Q52-54✓ CLINegligible overhead — single iframe, single message listener, no animation, no DOM polling.

Section 13 — Change Management (Q55-58)

Same model as oidc-snippet: each forge aspect submit is a new immutable static loader; FI versioning policy applies.

Section 14 — Compliance & Assurance (Q59-60)

Same as oidc-snippet: Forge CLI internal review documented; FI deployment review per the checklist.


mobile-vendor-chat-jsbridge — Completed Response

Mobile-only WebView template. Requests session token via native iOS / Android JSBridge; falls back to a configurable --token-endpoint for browser preview.

Section 1 — Architecture (Q1-4)

#StatusEvidence / How
Q1✓ CLIWebView IIFE → JSBridge tokenApiDetails (iOS webkit.messageHandlers / Android JSBridge) → native app issues HTTPS to FI backend → window.onTokenApiResponse(response) → load vendor SDK with token. Fallback path: __cdxFetch to --token-endpoint.
Q2✓ CLIFI (mobile app, native bridge implementation, token endpoint), Vendor (chat SDK), Candescent (CLI).
Q3✓ CLIFI native: bridge implementation, credential injection. FI backend: token issuance. Vendor: chat SDK. CLI: bridge invocation, token-response validation, vendor-SDK init.
Q4✓ CLIStatic loader = FI-hosted (HTML wrapped). Token endpoint = FI. Vendor SDK = vendor's CDN. UI = vendor's chat widget.

Section 2 — Trust Boundaries (Q5-8)

#StatusEvidence / How
Q5✓ CLIAll JS runs inside the WebView (the only "window" in mobile execution).
Q6✓ CLIWebView DOM only. No iframe, no Shadow DOM.
Q7✓ CLIWebView ↔ native app (JSBridge). WebView ↔ vendor CDN (HTTPS, optional SRI). WebView ↔ FI backend (HTTPS fallback).
Q8◯ FIVendor SDK URL hardcoded at submission via --vendor-script-url. Token endpoint via --token-endpoint. FI verifies these in the submission PR.

Section 3 — Static vs Dynamic / SRI (Q9-11)

#StatusEvidence / How
Q9✓ CLIStatic loader (HTML+IIFE): JSBridge invocation, fallback fetch, vendor-SDK script-tag construction (with optional SRI), event dispatch.
Q10✓ CLIDynamic = vendor SDK (its own logic loads after the script tag), session token (opaque). Token does not introduce new entry points.
Q11◯ FIStatic loader immutable per submission. SRI on vendor SDK supported via --integrity flag; FI provides the published vendor hash.

Section 4 — Context Handling (Q12-16)

#StatusEvidence / How
Q12✓ CLISession token (from FI native app via JSBridge, or fallback fetch). Vendor org id / app name (configured at submit time).
Q13✓ CLIiOS: window.webkit.messageHandlers.tokenApiDetails.postMessage('cdx-aspect'). Android: window.JSBridge.tokenApiDetails('cdx-aspect'). Response: window.onTokenApiResponse(JSON-or-string).
Q14✓ CLIResponse parsed (string → JSON tolerantly), token extracted from access_token or token field, type-checked. Empty / missing token logs a warning and degrades to vendor SDK without auth.
Q15✓ CLIToken written to window.VendorAuthToken for vendor SDK to consume. CustomEvent cdx-mobile-vendor-ready dispatched after SDK loads.
Q16◯ FIToken comes from FI's native app or FI backend over HTTPS — trust transferred from FI's native auth. Vendor SDK's own token validation is the vendor's responsibility.

Section 5 — Communication Back to Parent (Q17-20)

#StatusEvidence / How
Q17✓ CLIDOM event: cdx-mobile-vendor-ready (detail = {token, app, org, source}). Vendor SDK behavior beyond that is vendor-specific.
Q18✓ CLIToken-response shape tolerant: {access_token: string} or {token: string} accepted. Other fields ignored.
Q19◯ FIwindow.onTokenApiResponse is a global function callable by anyone with WebView access. In a real WebView, only the native bridge calls it; in browser preview, the fallback __cdxFetch calls it. FI is responsible for ensuring no other JS in the WebView is hostile.
Q20✓ CLILoading the vendor SDK + dispatching cdx-mobile-vendor-ready. No further parent-site actions.

Section 6 — Rendering & XSS (Q21-24)

#StatusEvidence / How
Q21✓ CLIVendor SDK draws its own UI inside the WebView. The CLI's IIFE renders nothing visible.
Q22✓ CLINone in the IIFE. The vendor SDK's innerHTML usage is the vendor's responsibility (covered by their own security review).
Q23✓ CLIToken / org id / app name written to window.* properties via property assignment, not innerHTML. No string concatenation into HTML.
Q24✓ CLINo eval / new Function / inline scripts in the IIFE. (Vendor SDK's own use is out of scope.)

Section 7 — UI / Design System (Q25-28)

#StatusEvidence / How
Q25-28◯ FI / vendorUI is the vendor SDK's. FI must validate vendor's design-system fit and CSS isolation in the WebView.

Section 8 — Resiliency (Q29-33)

#StatusEvidence / How
Q29✓ CLIJSBridge unavailable → falls back to __cdxFetch to --token-endpoint. Vendor SDK load failure → existing partner-script onerror diagnostics fire. Token-endpoint timeout → user sees [cdx-aspect:<id>] mobile-vendor-chat: token fallback timed out (<ms>).
Q30✓ CLI10 000 ms default on the fallback fetch; override via --timeout-ms.
Q31◯ FI / vendorNo CLI-rendered UX (template's UI is the vendor's). FI / vendor own the failure UX.
Q32✓ CLIToken missing → vendor SDK loads with empty token (fail-open with logged warning).
Q33✓ CLISame as oidc-snippet: 3 retries default with exponential backoff on 5xx / network errors via __cdxFetch.

Section 9 — Troubleshooting (Q34-37)

Same as hidden-iframe-sso: correlation-id-tagged log lines, browser-log pipeline. Common signals: JSBridge call failed, token response missing access_token, token fallback timed out.

Section 10 — Logging (Q38-41)

Same as oidc-snippet. The vendor SDK's own logging is vendor-controlled.

Section 11 — Libraries (Q42-45)

#StatusEvidence / How
Q42◯ FIThe vendor SDK is loaded dynamically. Its libraries are out of CLI scope. The CLI's IIFE itself uses none.
Q43✓ CLI / ◯ vendorCLI's IIFE bundled. Vendor SDK loaded dynamically from --vendor-script-url.
Q44✓ CLICLI side: IIFE scope, __cdx* prefix. Vendor SDK conflict prevention is the vendor's responsibility.
Q45◯ documentedGlobals introduced: window.VendorAppName, window.VendorOrgId, window.VendorAuthToken, window.onTokenApiResponse. Documented for FI awareness.

Section 12 — FI Compatibility (Q46-54)

#StatusEvidence / How
Q46✓ CLICompatible with WebView execution. No conflict with native bridges other than the documented tokenApiDetails.
Q47✓ CLI documentedReads: window.webkit.messageHandlers.tokenApiDetails, window.JSBridge.tokenApiDetails. Writes: window.VendorAppName, window.VendorOrgId, window.VendorAuthToken, window.onTokenApiResponse.
Q48✓ CLINo framework dependency.
Q49✓ CLINone added by the IIFE itself. (window.onTokenApiResponse is a function, not a listener.)
Q50✓ CLIcdx-mobile-vendor-ready event uses cdx- prefix.
Q51✓ CLItry/catch around bridge invocation; fallback fetch wrapped in .catch.
Q52-54✓ CLIAsync <script> tag for vendor SDK. Bridge call is synchronous but native side is non-blocking.

Section 13 — Change Management (Q55-58)

Same model as the others.

Section 14 — Compliance & Assurance (Q59-60)

Same as the others.


Other Templates — Shared Response Summaries

The remaining 12 templates fall into three families with shared questionnaire responses. Differences are noted inline.

Family A — Context-less UI Templates

Templates: banner, toast, card, modal, countdown, floating-action-button

These render a UI element (banner / toast / card / modal / countdown timer / floating button) directly into the parent DOM. They do not read user identity, do not call external services, and do not communicate back to the parent beyond a click handler.

SectionHeadline answer
1 — Architecture (Q1-4)Static IIFE → DOM render. No runtime APIs. FI hosts the loader; Candescent provides the template.
2 — Trust boundaries (Q5-8)Parent DOM only. No iframe, no Shadow DOM, no external network.
3 — Static vs dynamic / SRI (Q9-11)Static loader is immutable. No dynamic content. SRI n/a (no external scripts loaded).
4 — Context (Q12-16)n/a — no contextual data read.
5 — Communication (Q17-20)None back to the parent except: (a) modal / card navigate via validated --cta-url (http: / https: only); (b) floating-action-button opens a new tab via window.open(url, '_blank', 'noopener,noreferrer').
6 — Rendering / XSS (Q21-24)innerHTML used; --message, --cta-text, validated --cta-url, all __cdxEsc-escaped at generation time. No eval / new Function / inline event handlers.
7 — UI / design (Q25-28)--bg-color, --text-color, --position flags supported. Shadow DOM not implemented — FI verifies parent-CSS impact. CSP nonce on <style> via --csp-nonce.
8 — Resiliency (Q29-33)No failure modes (no network calls). Render failure (e.g. document.body missing) is silent.
9-10 — Troubleshooting / Logging (Q34-41)Minimal console.*. No correlation id (no telemetry consumer).
11 — Libraries (Q42-45)None. countdown introduces window._cdxCountdownIv (cleared on dismiss). Otherwise no globals.
12 — Compatibility (Q46-54)No framework dependency. No dbk.* reads. No global event listeners (only element-scoped addEventListener on close buttons).
13-14 — Governance (Q55-60)Standard: each submit = new immutable loader; FI controls rollback. AppSec review per FI policy.

Family B — Personalized UI Templates

Templates: welcome-banner, personalized-toast

Same as Family A, but additionally read dbk.sessionInfo() for the user's first name. Differences from Family A:

SectionDifference
4 — Context (Q12-16)Reads dbk.sessionInfo() (Q12, Q13). Validated by inlined __cdxValidateSession (Q14): type, length ≤ 200, Unicode-letter allowlist, optional sessionExpiry future-check. Falls back to "Valued Customer" / "there" on validation failure (Q16).
6 — Rendering / XSS (Q21-24)Validated user name passes through __cdxEsc before insertion into innerHTML (Q23). Same XSS guarantees as Family A.
12 — Compatibility (Q47)Depends on dbk.sessionInfo (parent-site global). Type-checked before use; degrades gracefully when absent.

Family C — Vendor-Loader Templates

Templates: vendor-script-loader, vendor-script-with-config, tag-manager, vendor-sdk-personalized

Load an external vendor script (and, in vendor-script-with-config, an external CSS file). The vendor SDK then runs in the parent window with whatever permissions the FI's CSP allows.

SectionHeadline answer
1 — Architecture (Q1-4)Parent IIFE → <script> (and optional <link>) loads vendor SDK. Vendor SDK owns runtime behavior thereafter.
2 — Trust boundaries (Q5-8)Parent DOM. Vendor SDK domain set at submission via --vendor-script-url / --css-url; FI verifies in the submission PR (Q8).
3 — Static vs dynamic / SRI (Q9-11)SRI supported for both vendor JS and (for vendor-script-with-config) CSS via --integrity / --css-integrity. CLI bypasses dbk.loadScript when SRI is set. Malformed hashes fail-open with console.error.
4 — Context (Q12-16)vendor-sdk-personalized reads dbk.sessionInfo() and pre-seeds the vendor SDK with userFullName, userGuid via window.PreChatFields etc. — same __cdxValidateSession enforcement as Family B. Other vendor loaders read no context.
5 — Communication (Q17-20)n/a — vendor-controlled after load.
6 — Rendering / XSS (Q21-24)CLI-side: no innerHTML of dynamic data, no eval. Vendor SDK's own behavior is the vendor's responsibility.
7 — UI / design (Q25-28)Vendor-styled. Shadow DOM not enforced.
8 — Resiliency (Q29-33)Script load failure: s.onerror fires partner-script diagnostics (probes /health on loopback hosts to detect "mock not running"). No retry on script load. Fetch resiliency in vendor-script-with-config config-globals: n/a (no fetch).
11 — Libraries (Q42-45)Vendor SDK is dynamically loaded (Q42-43). CLI scope: bundled IIFE only. vendor-sdk-personalized introduces globals: window.PreChatFields, window.VendorOrgId, window.VendorAppName, plus the configured --vendor-init-fn path (Q45). vendor-script-with-config introduces window.AspectConfigContent plus any extras from --config-globals.
12 — Compatibility (Q46-54)CLI side compatible. Vendor SDK conflict prevention is the vendor's responsibility (Q44, Q48).
9-10, 13-14Standard.

tag-manager is web-only; the others support both platforms. tag-manager additionally validates the GTM container id format (GTM-[A-Z0-9]+) at generation time — invalid ids emit console.error instead of a broken script tag.